package com.example.demo.service;

import com.example.demo.lock.JedisLock;
import com.example.demo.lock.LettuceLock;
import com.example.demo.lock.RedisLock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
@Slf4j
public class StockService {

    private final static int EXPIRE = 30000;

    private static int AMOUNT = 1000000;

    private final static String LOCK = "product_lock";

    @Autowired
    private Map<String, RedisLock> lockMap;

    public int getAmount() {
        return AMOUNT;
    }

    public static ExecutorService pool = null;

    @Autowired
    private Integer threadNum;

    @PostConstruct
    public void init() {
        System.out.println("----------------init---------" + threadNum);
        pool = Executors.newFixedThreadPool(threadNum);
    }

    /**
     * 消耗库存
     * @param lockName 并发锁名称
     * @param withLock 是否启用并发锁（用于测试线程安全问题）
     * @return
     */
    public boolean consumeTest(String lockName, boolean withLock) {
        final RedisLock redisLock = lockMap.get(lockName);
        if (withLock) {
            if (!redisLock.lock(LOCK, EXPIRE)) { //非阻塞
//            if (!redisLock.tryLock(LOCK, EXPIRE)) { //阻塞
                log.info("获取锁失败：{}", Thread.currentThread().getName());
                System.out.println("获取锁失败");
                return false;
            }
        }
        try {
            Thread.sleep(500); //模拟操作耗时
            AMOUNT -= 1;
            log.info("库存减1: {}", Thread.currentThread().getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (withLock) {
            final boolean release = redisLock.release(LOCK);
            log.info("删除锁结果：{}", release);
        }
        return true;
    }
}
